#include "../log_local/sink.hpp"

namespace ns_log
{
    enum class LogTimeGap
    {
        SECOND = 0,
        MINUTE,
        HOUR,
        DAY
    };

#define FormatAdjust(num, ch) std::setw(num) << std::setfill(ch)

    class RollSinkByTime : public FSLogSink
    {
    public:
        RollSinkByTime(const std::string &basename, LogTimeGap time_gap)
            : _basename(basename), _name_count(0), _prev_time(0)
        {
            if (time_gap == LogTimeGap::SECOND)
                _time_gap = 1;
            else if (time_gap == LogTimeGap::MINUTE)
                _time_gap = 60;
            else if (time_gap == LogTimeGap::HOUR)
                _time_gap = 3600;
            else if (time_gap == LogTimeGap::DAY)
                _time_gap = 3600 * 24;
        }

        virtual void log(const char *data, size_t len)
        {
            check();
            _ofs.write(data, len);
            if (!_ofs.good())
            {
                std::cout << "RollSinkByTime写入文件失败，文件基础名：" << _basename << "\n";
                abort();
            }
        }

    private:
        void check()
        {
            bool ok = !_ofs.is_open();
            time_t cur_time = DateHelper::now();
            if (_time_gap == 1 && _prev_time != cur_time)
                ok = true;
            else if (_time_gap != 1 && _prev_time % _time_gap == cur_time % _time_gap)
                ok = true;
            if (ok)
            {
                _prev_time = cur_time;
                std::string newFile = createNewFile();
                FileHelper::createDir(FileHelper::getPath(newFile));
                if (_ofs.is_open())
                    _ofs.close();
                _ofs.open(newFile, std::ios::binary | std::ios::app);
                if (!_ofs.is_open())
                {
                    std::cout << "RollSinkByTime写入文件失败，文件基础名：" << _basename << "\n";
                    abort();
                }
            }
        }

        std::string createNewFile()
        {
            std::ostringstream oss;
            time_t now = DateHelper::now();
            struct tm *tm = localtime(&now);
            oss << _basename << tm->tm_year + 1900 << FormatAdjust(2, '0') << tm->tm_mon + 1 << FormatAdjust(2, '0') << tm->tm_mday
                << FormatAdjust(2, '0') << tm->tm_hour << FormatAdjust(2, '0') << tm->tm_min << FormatAdjust(2, '0') << tm->tm_sec
                << "-" << _name_count++ << ".log";
            return oss.str();
        }

        std::string _basename;
        std::ofstream _ofs;
        size_t _name_count;
        time_t _prev_time;
        size_t _time_gap;
    };
}

using namespace ns_log;

int main()
{
    FSLogSink::ptr sp = LogSinkFactory::create_fs<RollSinkByTime>("./log/roll-", LogTimeGap::SECOND);
    const std::string str = "Hello World\n";
    time_t now = DateHelper::now();
    while (DateHelper::now() < now + 5) // 给5s
    {
        sp->log(&str[0], str.size());
    }
    return 0;
}
